package com.hvgroup.modules.sanic.web;

import com.hvgroup.annotation.Log;
import com.hvgroup.annotation.rest.AnonymousPostMapping;
import com.hvgroup.modules.sanic.constants.SysCodeEnum;
import com.hvgroup.modules.sanic.domain.dto.TaskResult;
import com.hvgroup.modules.sanic.domain.po.LlmApp;
import com.hvgroup.modules.sanic.repository.LlmAppRepository;
import com.hvgroup.modules.sanic.service.FileChatService;
import com.hvgroup.modules.sanic.util.FileUploader;
import com.hvgroup.modules.sanic.util.MinioUtil;
import com.hvgroup.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/file")
@Api(tags = "系统:会话管理")
public class FileChatController {

    private final MinioUtil minioUtil;
    private final FileChatService fileChatService;
    //    private final ApiTokenRepository apiTokenRepository;
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.buckets}")
    private String buckets;
    @Value("${dify.api.fileUrl}")
    private String fileUrl;

    @Log("读取文件")
    @ApiOperation("读取文件")
    @AnonymousPostMapping("/read_file")
    public ResponseEntity<Object> readFile(@RequestParam(value = "file_qa_str", required = false) String fileQaStr,
                                           @RequestBody(required = false) Map<String, Object> body) {
        try {
            // 参数提取：优先从 query 参数拿，拿不到就从 JSON body 里取
            if (fileQaStr == null && body != null) {
                fileQaStr = (String) body.get("file_qa_str");
            }

            if (StringUtils.isEmpty(fileQaStr)) {
//                throw new MyException(SysCodeEnum.C_400, "file_qa_str 参数不能为空");
                throw new Exception(SysCodeEnum.C_400 + "file_qa_str 参数不能为空");

            }

            // 取文档 key
            String fileKey = fileQaStr.split("\\|")[0];

            // 获取文件的临时访问地址
            String fileUrl = minioUtil.getFileUrlByKey(fileKey);

            String result = fileChatService.readExcel(fileUrl);

//            return Response.success(result);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("读取 Excel 文件失败", e);
            return ResponseEntity.internalServerError().body(e.getMessage());
//            throw new MyException(SysCodeEnum.C_9999);
        }
//        return null;
    }



    /**
     * 读取文件表头（第一行），支持 Excel 和 CSV 文件
     *
     * @param fileQaStr 文件 key（可能带有 | 分隔信息）
     * @return JSON 字符串形式的表头和数据预览
     */
    @AnonymousPostMapping("/read_file_column")
    public ResponseEntity<Map<String, Object>> readFileColumn(
            @RequestParam(value = "file_qa_str", required = false) String fileQaStr,
            @RequestBody(required = false) Map<String, Object> body) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (fileQaStr == null && body != null) {
                fileQaStr = (String) body.get("file_qa_str");
            }

            if (StringUtils.isEmpty(fileQaStr)) {
                throw new IllegalArgumentException("file_qa_str 参数不能为空");
            }

            String fileKey = fileQaStr.split("\\|")[0];
            String fileUrl = minioUtil.getFileUrlByKey(fileKey);
            String columns = fileChatService.readFileColumns(fileUrl);

            resultMap.put("code", 200);
            resultMap.put("msg", "ok");
            resultMap.put("data", columns);
            return ResponseEntity.ok(resultMap);

        } catch (Exception e) {
            resultMap.put("code", 500);
            resultMap.put("msg", "读取文件列失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultMap);
        }
    }



    /**
     * 通过 object_key 获取文件内容并执行查询逻辑
     */
    @GetMapping("/query_excel")
    public ResponseEntity<String> processQuery(@RequestParam String query) {
        try {
            // 解析 query_str（格式：text@@@@fileKey）
            String decoded = URLDecoder.decode(query, StandardCharsets.UTF_8.name());
            if (decoded == null || !decoded.contains("@@@@")) {
                return ResponseEntity.badRequest().body("{\"error\": \"Invalid query string format\"}");
            }

            String[] split = decoded.replace("&", "").replace("=", "").split("@@@@");
            String queryText = split[0];
            String fileKey = split[1];

            // 获取 MinIO 文件地址
            String fileUrl = minioUtil.getFileUrlByKey(fileKey);

            // 执行查询逻辑（你需在 excelQueryService 实现 queryExcel 方法）
            String result = fileChatService.queryExcel(fileUrl, queryText);

            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                    .body("{\"error\": \"" + e.getMessage() + "\"}");
        }
    }


    /**
     * 上传附件（从 multipart 表单读取文件，并上传到 MinIO）
     */
    @AnonymousPostMapping("/upload_file")
    public ResponseEntity<Map<String, String>> uploadFile(@RequestParam("file") MultipartFile file) {
        Map<String, String> result = new HashMap<>();
        try {
            String bucket = "filedata"; // 默认桶名，也可以作为参数传进来
            String fileName = file.getOriginalFilename();
            String contentType = file.getContentType();
            InputStream inputStream = file.getInputStream();
            long size = file.getSize();

            // 上传并获取文件 key
            String objectKey = minioUtil.uploadFile(inputStream, size, bucket, fileName, contentType);

            // 获取预签名 URL
            String fileUrl = minioUtil.getPresignedUrl(bucket, objectKey);

            result.put("object_key", objectKey);
            result.put("url", fileUrl);
            result.put("download_url", endpoint + "/" + bucket + "/" + objectKey);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(result);
        }
    }

    private final LlmAppRepository llmAppRepository;

    @AnonymousPostMapping("/upload")
    public String handleUpload(@RequestParam("file") MultipartFile file,
                               @RequestParam("appId") String appId,
                               @RequestParam("userId") String userId) {
        try {
            LlmApp apiToken = llmAppRepository.findFirstByAppId(appId)
                    .orElseThrow(() -> new RuntimeException("请选择应用!"));
            String apiKey = apiToken.getAccessToken();
            return new FileUploader().uploadFile(file, apiKey, userId,fileUrl);
        } catch (RuntimeException e) {
            return e.getMessage();
        }
    }

    /**
     * 文件问答处理大模型输出 SQL（来自文件 + 模型输出）
     */
    @AnonymousPostMapping("/process_file_llm_out")
    public ResponseEntity<Object> processFileLlmOut(
            @RequestParam("file_key") String fileKey,
            @RequestBody String bodyStr
    ) {
        try {
            log.info("query param: {}", bodyStr);

            Object result = fileChatService.processFileLlmQuery(fileKey, bodyStr);
            return ResponseEntity.ok(TaskResult.success(result));
        } catch (Exception e) {
            log.error("Error processing LLM output", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("{\"error\": \"" + e.getMessage() + "\"}");
        }
    }
}
